<?php

namespace common\utils;

use Illuminate\Support\Facades\Log;


class PartnerSDK
{
    /**
     * API地址
     * 
     * @var string
     */
    public $baseUrl;

    /**
     * 超时时间
     * 
     * @var int
     */
    public $timeout;

    /**
     * 请求返回对象
     * 
     * @var \Psr\Http\Message\ResponseInterface
     */
    public $resp;

    /**
     * 错误信息
     * 
     * @var array
     */
    public $errors = [];

    /**
     * @param string $baseUrl API地址
     * @param int    $timeout 超时时间
     */
    public function __construct($baseUrl = '', $timeout = 30)
    {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->timeout = $timeout;
    }

    /**
     * 获取错误信息
     * 
     * @return array
     */
    public function getErrors()
    {
        return $this->errors;
    }

    /**
     * 获取返回对象
     * 
     * @return \Psr\Http\Message\ResponseInterface
     */
    public function getResponse()
    {
        return $this->resp;
    }


    /**
     * 登录
     * 
     * @param string $gameType 游戏类型 AG HC
     * @param string $username 用户名
     * @param string $password 密码
     * @param string $isTrial  是否试玩用户
     * @param array  $options  可选参数
     * 
     * @return false|array
     */
    public function login($gameType, $username, $password, $isTrial, $options = [])
    {
        $data = [
            'api_name' => $gameType,
            'username' => $username,
            'password' => $password,
            'is_trial' => $isTrial,
        ];
        return $this->exec('/api/login', 'POST', array_merge($data, $options));
    }

    /**
     * 注册
     * 
     * @param string $gameType 游戏类型 AG HC
     * @param string $username 用户名
     * @param string $password 密码
     * @param array  $options  可选参数
     * 
     * @return false|array
     */
    public function register($gameType, $username, $password, $options = [])
    {
        $data = [
            'api_name' => $gameType,
            'username' => $username,
            'password' => $password,
        ];
        return $this->exec('/api/register', 'POST', array_merge($data, $options), false);
    }

    /**
     * 转账
     * 
     * @param string $gameType 游戏类型 AG HC
     * @param string $username 用户名
     * @param string $password 密码
     * @param string $orderNumber 订单号
     * @param string $amount   转账金额
     * @param array  $options  可选参数
     * 
     * @return false|array
     */
    public function transfer($gameType, $username, $password, $orderNumber, $amount, $options = [])
    {
        $data = [
            'api_name' => $gameType,
            'username' => $username,
            'password' => $password,
            'transaction_no' => $orderNumber,
            'amount' => $amount,
        ];
        return $this->exec('/api/transfer', 'POST', array_merge($data, $options), false);
    }

    /**
     * 获取余额
     * 
     * @param string $gameType 游戏类型 AG HC
     * @param string $username 用户名
     * @param string $password 密码
     * @param array  $options  可选参数
     * 
     * @return false|array
     */
    public function getBalance($gameType, $username, $password, $options = [])
    {
        $data = [
            'api_name' => $gameType,
            'username' => $username,
            'password' => $password,
        ];
        return $this->exec('/api/getBalance', 'GET', array_merge($data, $options), false);
    }

    /**
     * 获取订单
     * 
     * @param string $gameType  游戏类型 AG HC
     * @param string $startTime 开始时间（时间戳）
     * @param string $endTime   结束时间（时间戳）
     * @param array  $options   可选参数
     * 
     * @return array
     */
    public function getOrders($gameType, $startTime, $endTime, $options = [])
    {
        $data = [
            'api_name' => $gameType,
            'start_time' => $startTime,
            'end_time' => $endTime,
        ];
        // 直接返回data数据，报错直接退出
        $ret = $this->exec('/api/getOrders', 'GET', array_merge($data, $options));
        return $ret["data"];
    }

    /**
     * 网银支付，前端支持银行卡
     * 
     * @param string $code 
     * 
     * @return false|array
     */
    public function getBankList($code)
    {
        return $this->exec('/payment/bankList', 'GET', ['code' => $code]);
    }

    /**
     * 请求第三方支付
     * 
     * @param string $hallID       厅id
     * @param string $userID       用户id
     * @param string $orderNumber  订单id
     * @param string $money        金额 单位 厘 ；在具体的支付里面再格式化为需要的单位
     * @param string $payID        支付渠道配置id
     * @param string $paySceneID   支付场景id
     * @param string $scene        支付场景
     * @param string $code         支付平台code
     * @param string $source       支付设备类型
     * @param string $ip           支付设备ip
     * @param string $bankCode     银行简称 网银支付使用
     * 
     * @return false|array
     */
    public function doPay(
        $hallID,
        $userID,
        $orderNumber,
        $money,
        $payID,
        $paySceneID,
        $scene,
        $code,
        $source,
        $ip,
        $bankCode
    ) {
        $params = [
            'hall_id' => $hallID,
            'user_id' => $userID,
            'order_number' => $orderNumber,
            'money' => $money,
            'pay_id' => $payID,
            'pay_scene_id' => $paySceneID,
            'scene' => $scene,
            'code' => $code,
            'source' => $source,
            'ip' => $ip,
            'bank_code' => $bankCode,
            'server' => $_SERVER, // 服务器信息， 用于计算回调地址
        ];
        return $this->exec('/payment/doPay', 'POST', $params, false);
    }

    /**
     * 执行命令
     * 
     * @param string $url    请求地址
     * @param string $method 请求api的方法，get，post，patch 等
     * @param array  $data   数据，body数据，param 数据等
     * @param bool   $exit   出错了直接退出，某些API要处理后续逻辑，不能直接退出，如转账，支付等
     * 
     * @return null|\Psr\Http\Message\ResponseInterface
     */
    private function exec($url, $method, $data, $exit = true)
    {
        $url = $this->baseUrl . '/' . ltrim($url, '/');
        $resp = request($url, $method, $data, [], true, [], $this->timeout);
        $this->resp = $resp;
        $ret = json_decode($resp->getBody()->getContents(), true);
        
        // 统一处理错误
        if (!isset($ret["code"]) || $ret["code"] != SysCode::OK) {
            $this->errors = [
                'url' => $url,
                'method' => $method,
                'data' => $data,
                'status' => $resp->getStatusCode(),
                'ret' => $ret
            ];
            Log::error("Partner Server Request Error: ", $this->errors);
            if ($exit) {
                // 出错直接退出
                if (env('APP_DEBUG') == true) {
                    return error_exit(SysCode::INTERNAL_SERVER_ERROR, "Partner Server Error!", $this->errors);
                } else {
                    return error_exit(SysCode::INTERNAL_SERVER_ERROR);
                }
            } else {
                // curl报错：网络连接，超时等不可预知错误
                if ($resp->getStatusCode() < 100) {
                    return null;
                }
            }
        }
        return $ret;
    }
}